package com.bocloud.cmp.service.config;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bocloud.cmp.dao.ApplyRecordDao;
import com.bocloud.cmp.dao.ApproveNodeDao;
import com.bocloud.cmp.dao.MessageDao;
import com.bocloud.cmp.entity.ApplyRecord;
import com.bocloud.cmp.entity.ApproveNode;
import com.bocloud.cmp.entity.Message;
import com.bocloud.cmp.enums.ApplyStatus;
import com.bocloud.cmp.enums.MessageStatus;
import com.bocloud.cmp.interfaces.config.ApplyRecordService;
import com.bocloud.cmp.interfaces.resource.CloudServerService;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.coordinator.harmony.HarmonyLock;
import com.bocloud.coordinator.harmony.LockFactory;
import com.bocloud.soc.dao.intf.UserDao;
import com.bocloud.soc.entity.User;
import com.google.common.collect.Maps;

/**
 * 申请记录抽象Service接口实现
 * 
 * @author dongkai
 *
 */
@Service("applyRecordService")
public class ApplyRecordServiceImpl implements ApplyRecordService {

	private Logger logger = LoggerFactory.getLogger(ApplyRecordServiceImpl.class);
	@Autowired
	private ApplyRecordDao applyRecordDao;
	@Autowired
	private ApproveNodeDao approveNodeDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private MessageDao messageDao;
	@Autowired
	private CloudServerService cloudServerService;
	@Autowired
	private LockFactory lockFactory;

	@Override
	public BsmResult list(Integer page, Integer rows, List<Param> params, Map<String, String> sorter, Boolean simple,
			Long userId) {
		GridBean gridBean = null;
		try {
			if (null == params) {
				params = new ArrayList<Param>();
			}
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			List<ApplyRecord> applyRecords = null;
			int count = applyRecordDao.count(params);
			if (count != 0) {
				applyRecords = applyRecordDao.list(page, rows, params, sorter);
				for (ApplyRecord applyRecord : applyRecords) {
					switch (applyRecord.getCatalog()) {
					default:
						break;
					}
				}
			}
			gridBean = GridHelper.getBean(page, rows, count, applyRecords);
			return new BsmResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("List cron task fail:", e);
			return new BsmResult(false, "查询失败");
		}
	}

	@Override
	public BsmResult deal(Long userId) {
		try {
			List<ApplyRecord> applyRecords = new ArrayList<>();
			List<ApproveNode> approveNodes = approveNodeDao.listByUid(userId, ApplyStatus.APPROVING.name());
			ApplyRecord applyRecord = null;
			for (ApproveNode approveNode : approveNodes) {
				// 优先级是1
				Integer priority = approveNode.getPriority();
				if (priority.equals(1)) {
					applyRecord = applyRecordDao.query(approveNode.getApplyId());
					applyRecords.add(applyRecord);
				} else {
					// 优先级不是1的查看上一级
					ApproveNode appNode = approveNodeDao.get(approveNode.getApplyId(), priority - 1);
					if (appNode.getStatus().equals(ApplyStatus.APPROVED.name())) {
						applyRecord = applyRecordDao.query(approveNode.getApplyId());
						applyRecords.add(applyRecord);
					}
				}
			}
			for (ApplyRecord aRecord : applyRecords) {
				User user = userDao.query(aRecord.getApplicant());
				if (null != user) {
					aRecord.setApplicantName(user.getName());
				}
			}
			return new BsmResult(true, applyRecords, "查询成功!");
		} catch (Exception e) {
			logger.error("list ApplyRecord error:", e);
			return new BsmResult(false, "查询失败!");
		}
	}

	@Override
	public BsmResult done(Integer page, Integer rows, List<Param> params, Map<String, String> sorter, Boolean simple,
			Long userId) {
		GridBean gridBean = null;
		try {
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			List<ApplyRecord> applyRecords = new ArrayList<>();
			int count = applyRecordDao.countDone(params, userId);
			if (count != 0) {
				applyRecords = applyRecordDao.done(page, rows, params, sorter, userId);
			}
			for (ApplyRecord applyRecord : applyRecords) {
				User user = userDao.query(applyRecord.getApplicant());
				if (null != user) {
					applyRecord.setApplicantName(user.getName());
				}
			}
			gridBean = GridHelper.getBean(page, rows, count, applyRecords);
			return new BsmResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("List cron task fail:", e);
			return new BsmResult(false, "查询失败");
		}
	}

	@Override
	public BsmResult detail(Long id) {
		try {
			ApplyRecord applyRecord = applyRecordDao.query(id);
			if (null == applyRecord) {
				return new BsmResult(false, "查询失败!");
			}
			List<ApproveNode> approveNodes = approveNodeDao.listByAid(applyRecord.getId());
			applyRecord.setApprovers(approveNodes);
			return new BsmResult(true, applyRecord, "查询成功!");
		} catch (Exception e) {
			logger.error("get ApplyRecord error:", e);
			return new BsmResult(false, "查询失败!");
		}
	}

	@Override
	public BsmResult approveDetail(Long id) {
		try {
			ApplyRecord applyRecord = applyRecordDao.query(id);
			if (null == applyRecord) {
				return new BsmResult(false, "查询失败!");
			}
			List<ApproveNode> approveResult = new ArrayList<>();
			List<ApproveNode> approveNodes = approveNodeDao.listByAid(id);
			for (ApproveNode approveNode : approveNodes) {
				if (approveNode.getStatus().equals(ApplyStatus.APPROVED.name())) {
					approveResult.add(approveNode);
					continue;
				}
				if (approveNode.getStatus().equals(ApplyStatus.APPROVING.name())) {
					approveResult.add(approveNode);
					break;
				}
			}
			applyRecord.setApprovers(approveResult);
			return new BsmResult(true, applyRecord, "查询成功!");
		} catch (Exception e) {
			logger.error("get ApplyRecord error:", e);
			return new BsmResult(false, "查询失败!");
		}
	}

	@Override
	public BsmResult approve(Long applyId, Long nodeId, String reason, Long userId) {
		try {
			User user = userDao.query(userId);
			if (null == user) {
				return new BsmResult(false, "失败!");
			}
			List<ApproveNode> approveNodes = approveNodeDao.listByAid(applyId);
			ApproveNode last = approveNodes.get(approveNodes.size() - 1);
			ApproveNode approveNode = approveNodeDao.query(nodeId);
			if (approveNode.getPriority().equals(last.getPriority())) {
				// 更新申请状态
				ApplyRecord applyRecord = applyRecordDao.query(applyId);
				applyRecord.setStatus(ApplyStatus.APPROVED.name());
				applyRecord.setGmtModify(new Date());
				applyRecord.setMenderId(userId);
				applyRecordDao.update(applyRecord);
				// 所有人申请通过，创建虚拟机
				cloudServerService.create(applyRecord.getParams(), applyRecord.getCreaterId());
			} else {
				// 给下一个人发送站内信
				ApproveNode next = approveNodeDao.get(applyId, approveNode.getPriority() + 1);
				if (null != next) {
					Message message = new Message();
					message.setName(next.getName());
					message.setContent(user.getName() + "已通过！");
					message.setSender(userId);
					message.setOwnerId(next.getApprover());
					message.setGmtCreate(new Date());
					message.setCreaterId(userId);
					message.setStatus(MessageStatus.UNREAD.name());
					messageDao.save(message);
				}
			}
			approveNode.setStatus(ApplyStatus.APPROVED.name());
			approveNode.setGmtModify(new Date());
			approveNode.setMenderId(userId);
			approveNode.setReason(reason);
			approveNode.setPassed(true);
			approveNodeDao.update(approveNode);
			// 给申请人发送站内信
			Message message = new Message();
			message.setName(approveNode.getName());
			message.setContent(user.getName() + "已通过！");
			message.setSender(userId);
			message.setOwnerId(approveNode.getApplicant());
			message.setGmtCreate(new Date());
			message.setCreaterId(userId);
			message.setStatus(MessageStatus.UNREAD.name());
			messageDao.save(message);
			return new BsmResult(true, "成功!");
		} catch (Exception e) {
			logger.error("approve error:", e);
			return new BsmResult(false, "失败!");
		}
	}

	@Override
	public BsmResult refuse(Long applyId, Long nodeId, String reason, Long userId) {
		try {
			User user = userDao.query(userId);
			if (null == user) {
				return new BsmResult(false, "失败!");
			}
			ApproveNode approveNode = approveNodeDao.query(nodeId);
			// 更新申请状态
			ApplyRecord applyRecord = applyRecordDao.query(applyId);
			applyRecord.setStatus(ApplyStatus.REFUSED.name());
			applyRecord.setGmtModify(new Date());
			applyRecord.setMenderId(userId);
			applyRecordDao.update(applyRecord);

			approveNode.setStatus(ApplyStatus.REFUSED.name());
			approveNode.setGmtModify(new Date());
			approveNode.setMenderId(userId);
			approveNode.setReason(reason);
			approveNode.setPassed(false);
			approveNodeDao.update(approveNode);
			// 给申请人发送站内信
			Message message = new Message();
			message.setName(approveNode.getName());
			message.setContent(user.getName() + "已拒绝！");
			message.setSender(userId);
			message.setOwnerId(approveNode.getApplicant());
			message.setGmtCreate(new Date());
			message.setCreaterId(userId);
			message.setStatus(MessageStatus.UNREAD.name());
			messageDao.save(message);
			return new BsmResult(true, "成功!");
		} catch (Exception e) {
			logger.error("refuse error:", e);
			return new BsmResult(false, "失败!");
		}
	}

	@Override
	public BsmResult applyUser() {
		try {
			List<User> users = userDao.listByRid(2l);
			List<SimpleBean> simpleBeans = new ArrayList<>();
			for (User user : users) {
				SimpleBean simpleBean = new SimpleBean(user.getId(), user.getName());
				simpleBeans.add(simpleBean);
			}
			return new BsmResult(true, simpleBeans, "查询成功!");
		} catch (Exception e) {
			logger.error("list applyUser error:", e);
			return new BsmResult(false, "查询失败!");
		}
	}

	@Override
	public BsmResult create(ApplyRecord record, Long userId) {
		try {
			record.setName("创建虚机申请" + new Date().getTime());
			record.setCreaterId(userId);
			record.setMenderId(userId);
			record.setOwnerId(userId);
			record.setApplicant(userId);
			record.setStatus(ApplyStatus.UNAPPLY.name());
			applyRecordDao.save(record);
			return new BsmResult(true, "添加申请成功");
		} catch (Exception e) {
			logger.error("Create apply fail:", e);
			return new BsmResult(false, "添加申请失败！");
		}
	}

	@Override
	public BsmResult apply(Long id, String content, String approvers, Long userId) {
		String path = ApplyRecord.class.getSimpleName() + "_" + id;
		HarmonyLock lock = null;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				return new BsmResult(false, "请求超时");
			}
			ApplyRecord applyRecord = applyRecordDao.query(id);
			if (null == applyRecord) {
				logger.warn("ApplyRecord data not exist");
				return new BsmResult(false, "数据不存在");
			}
			applyRecord.setStatus(ApplyStatus.APPROVING.name());
			applyRecord.setMenderId(userId);
			applyRecord.setContent(content);
			applyRecordDao.update(applyRecord);
			// 添加审批
			int i = 1;
			if (!("").equals(approvers)) {
				String[] approver = approvers.split(",");
				for (String string : approver) {
					Long ownerId = Long.valueOf(string);
					ApproveNode approveNode = new ApproveNode(ownerId, applyRecord.getId(), userId, false, null, i);
					approveNode.setGmtCreate(new Date());
					approveNode.setCreaterId(userId);
					approveNode.setName(applyRecord.getName());
					approveNode.setStatus(ApplyStatus.APPROVING.name());
					approveNodeDao.save(approveNode);
					if (i == 1) {
						// 站内信
						Message message = new Message();
						message.setName(applyRecord.getName());
						message.setContent(content);
						message.setSender(userId);
						message.setOwnerId(ownerId);
						message.setGmtCreate(new Date());
						message.setCreaterId(userId);
						message.setStatus(MessageStatus.UNREAD.name());
						messageDao.save(message);
					}
					i++;
				}
			}
			return new BsmResult(true, "申请成功！");
		} catch (Exception e) {
			logger.error("crontask apply fail:", e);
			return new BsmResult(false, "申请失败！");
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
	}

}
